package utils

import (
	"crypto/md5"
	"errors"
	"fmt"
	"ir/utils/ip2region"
	"math/rand"
	"net"
	"net/http"
	"os"
	"strconv"
	"strings"
)

//得到ip地址相关信息, 格式: 国家-省-城市
func GetIpInfo(ipAddress string) (string, error) {
	var ipDbPath string
	var ipTransfer *ip2region.Ip2Region
	pwd, pwdErr := os.Getwd()
	if pwdErr == nil {
		ipDbPath = pwd + "/config/ip2region.db"
	}
	if ipDbPath != "" {
		ipTransfer, _ = ip2region.New(ipDbPath)
		defer ipTransfer.Close()
		ip, ipErr := ipTransfer.BinarySearch(ipAddress)
		if ipErr != nil {
			return "", errors.New("解析失败")
		}
		if ip.Province == "0" && ip.Country == "0" && ip.Region == "" {
			return "", errors.New("未知地区")
		}
		ipStr := ""
		if ip.Country != "0" {
			ipStr += ip.Country
		}
		if ip.Province != "0" {
			ipStr += "-" + ip.Province
		}
		if ip.City != "0" {
			ipStr += "-" + ip.City
		}
		if ip.Region != "0" {
			ipStr += "-" + ip.Region
		}
		return ipStr, nil
	}
	return "", errors.New("IP加载错误")
}

// 得到用户的IP
func GetIp(req *http.Request) string {
	remoteAddr := req.RemoteAddr
	if ip := req.Header.Get("X-Real-IP"); ip != "" {
		remoteAddr = ip
	} else if ip = req.Header.Get("X-Forwarded-For"); ip != "" {
		remoteAddr = ip
	} else {
		remoteAddr, _, _ = net.SplitHostPort(remoteAddr)
	}

	if remoteAddr == "::1" {
		remoteAddr = "127.0.0.1"
	}
	return remoteAddr
}

// MD5 md5加密
func MD5(message string) string {
	res := md5.Sum([]byte(message))
	return fmt.Sprintf("%x", res)
}

func EncryptPassword(password, salt, uniqueChars string) string {
	pwdSeed := fmt.Sprintf("%s.%s.%s", uniqueChars, password, salt)
	return MD5(pwdSeed)
}

func InArrayInt(ele int, arr []int) (exists bool, index int) {
	exists = false
	index = -1
	for k, v := range arr {
		if v == ele {
			index = k
			exists = true
		}
	}
	return
}

func InArrayFloat64(ele float64, arr []float64) (exists bool, index int) {
	exists = false
	index = -1
	for k, v := range arr {
		if v == ele {
			index = k
			exists = true
		}
	}
	return
}

// InArray 检测字符串数组中是否存在某个元素
func InArray(ele string, arr []string) (exists bool, index int) {
	exists = false
	index = -1
	for k, v := range arr {
		if v == ele {
			index = k
			exists = true
		}
	}
	return
}

// ZeroBeforeSingleDigits 个位数字前补零
func ZeroBeforeSingleDigits(val int) string {
	strVal := strconv.Itoa(val)
	if val < 10 {
		strVal = "0" + strVal
	}
	return strVal
}

// RandInt 调用前需要设置(在for外) rand.Seed(time.Now().UnixNano())
func RandInt(min, max int) int {
	n := max - min + 1
	return rand.Intn(n) + min
}

// IsNumeric is_numeric()
func IsNumeric(val interface{}) bool {
	switch val.(type) {
	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, complex64, complex128:
		return true
	case string:
		str := val.(string)
		if str == "" {
			return false
		}
		// Trim any whitespace
		str = strings.Trim(str, " \\t\\n\\r\\v\\f")
		if str[0] == '-' || str[0] == '+' {
			if len(str) == 1 {
				return false
			}
			str = str[1:]
		}
		// hex
		if len(str) > 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') {
			for _, h := range str[2:] {
				if !((h >= '0' && h <= '9') || (h >= 'a' && h <= 'f') || (h >= 'A' && h <= 'F')) {
					return false
				}
			}
			return true
		}
		// 0-9,Point,Scientific
		p, s, l := 0, 0, len(str)
		for i, v := range str {
			if v == '.' { // Point
				if p > 0 || s > 0 || i+1 == l {
					return false
				}
				p = i
			} else if v == 'e' || v == 'E' { // Scientific
				if i == 0 || s > 0 || i+1 == l {
					return false
				}
				s = i
			} else if v < '0' || v > '9' {
				return false
			}
		}
		return true
	}
	return false
}
